package com.nineclock.document.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.entity.Result;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.document.dto.DocFileDto;
import com.nineclock.document.dto.DocFolderDto;
import com.nineclock.document.dto.DocumentDto;
import com.nineclock.document.dto.DocumentUserDTO;
import com.nineclock.document.enums.DocumentPermissionEnum;
import com.nineclock.document.mapper.DocCollaborationsMapper;
import com.nineclock.document.pojo.DocCollaborations;
import com.nineclock.document.pojo.DocFile;
import com.nineclock.document.pojo.DocFolder;
import com.nineclock.document.mapper.DocFileMapper;
import com.nineclock.document.mapper.DocFolderMapper;
import com.nineclock.document.service.DocFileService;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.feign.SysUserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional
public class DocFileServiceImpl implements DocFileService {

    @Autowired
    private DocFileMapper fileMapper;
    @Autowired
    private DocFolderMapper folderMapper;
    @Autowired
    private SysUserFeign sysUserFeign;
    @Autowired
    private DocCollaborationsMapper collaborationsMapper;

    /**
     * 查询当前目录下的 子文件夹及文件
     *
     * @param parentFolderId
     * @return
     */
    @Override
    public DocumentDto listFolderAndFile(Long parentFolderId) {
        //获取companyId
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //1. 查询符合条件的文件夹列表 queryFolders()
        List<DocFolderDto> folders = queryFolders(parentFolderId, companyId);

        //2. 查询符合条件的文件列表 queryFiles()
        List<DocFileDto> files = queryFiles(parentFolderId, companyId);

        //3. 组装数据并返回
        DocumentDto documentDto = new DocumentDto(folders, files);
        return documentDto;
    }

    /**
     * 根据文档ID查询文档信息
     *
     * @param id
     * @return
     */
    @Override
    public DocFileDto getFileByFileId(Long id) {
        //校验
        if (id == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //根据ID查询
        DocFile docFile = fileMapper.selectById(id);
        return BeanHelper.copyProperties(docFile, DocFileDto.class);
    }

    /**
     * 根据文档ID查询文档的详情信息(分页查询)
     *
     * @param fileId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<DocumentUserDTO> pagingCollaborations(Long fileId, Long page, Long pageSize) {
        //1. 参数校验
        if (fileId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //2. 根据文档ID 查询协作者ID (分页查询)
        //page对象
        Page<DocCollaborations> p = new Page<>(page, pageSize);
        //组装查询条件
        LambdaQueryWrapper<DocCollaborations> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DocCollaborations::getFileId, fileId);
        //分页查询 --> 得到分页结果
        Page<DocCollaborations> collaborationsPage = collaborationsMapper.selectPage(p, wrapper);
        //得到分页查询的结果列表
        List<DocCollaborations> records = collaborationsPage.getRecords();

        //从结果列表获取 协作者ID
        List<Long> Ids = records.stream().map(docCollaborations -> {
            return docCollaborations.getCollaborationId();
        }).collect(Collectors.toList()); //遍历获取到协作者ID 封装到集合

        //3. 组装协作者信息
        List<DocumentUserDTO> documentUserDTOS = new ArrayList<>();
        for (Long id : Ids) {
            //根据ID查询员工信息
            Result<SysCompanyUserDTO> result = sysUserFeign.queryByCompanyUserId(id);
            SysCompanyUserDTO userDTO = result.getData();

            DocumentUserDTO documentUserDTO = new DocumentUserDTO(id,userDTO.getUserName());
            documentUserDTOS.add(documentUserDTO);
        }

        //4. 返回
        return new PageResult<DocumentUserDTO>(p.getTotal(),p.getPages(),documentUserDTOS);
    }

    /**
     * 获取指定目录下的文件(具有权限的)
     *
     * @param parentFolderId
     * @param companyId
     * @return
     */
    private List<DocFileDto> queryFiles(Long parentFolderId, Long companyId) {

        //1. 查询文档 -- 公共读 / 公共读写
        LambdaQueryWrapper<DocFile> fileWrapper1 = new LambdaQueryWrapper<>();
        fileWrapper1.eq(DocFile::getCompanyId, companyId);
        fileWrapper1.eq(DocFile::getFolderId, parentFolderId);
        // ALL_READ,ALL_READ_WRITE
        fileWrapper1.in(DocFile::getPermission, DocumentPermissionEnum.ALL_READ.getPermission(), DocumentPermissionEnum.ALL_READ_WRITE.getPermission());
        //状态码status=1,没有封禁
        fileWrapper1.eq(DocFile::getStatus, (short) 1);

        List<DocFile> fileList1 = fileMapper.selectList(fileWrapper1);

        //2. 查询文档 -- 员工自己私有
        LambdaQueryWrapper<DocFile> fileWrapper2 = new LambdaQueryWrapper<>();
        fileWrapper2.eq(DocFile::getCompanyId, companyId);
        fileWrapper2.eq(DocFile::getFolderId, parentFolderId);
        fileWrapper2.in(DocFile::getPermission, DocumentPermissionEnum.PRIVATE_READ_WRITE.getPermission());
        fileWrapper2.eq(DocFile::getStatus, (short) 1);
        //文档创建人是当前用户
        fileWrapper2.eq(DocFile::getCreateUserId, CurrentUserHolder.get().getCompanyUserId());

        List<DocFile> fileList2 = fileMapper.selectList(fileWrapper2);

        //3. 查询文档 -- 当前用户是协作者的文档(多表查询,自定义sql)
        Long companyUserId = CurrentUserHolder.get().getCompanyUserId();
        List<DocFile> fileList3 = fileMapper.queryFileListByCollaboration(companyUserId, parentFolderId);

        //4.整合查询到的三个文档集合
        List<DocFile> allFiles = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(fileList1)) {
            allFiles.addAll(fileList1);
        }
        if (CollectionUtil.isNotEmpty(fileList2)) {
            allFiles.addAll(fileList2);
        }
        if (CollectionUtil.isNotEmpty(fileList3)) {
            allFiles.addAll(fileList3);
        }

        //5. 组装数据
        HashSet<DocFile> fileset = new HashSet<>(allFiles); //利用set集合 去重!!!
        Set<DocFileDto> fileDtoSet = BeanHelper.copyWithCollection(fileset, DocFileDto.class);

        //6. 组装用户名 和 最后更新人名称
        //遍历set
        List<DocFileDto> files = fileDtoSet.stream().map(docFileDto -> {
            //获取用户ID和最后更新人的ID
            Long createUserId = docFileDto.getCreateUserId();
            Long updateUserId = docFileDto.getUpdateUserId();
            //调用Feign接口 查询用户信息
            SysCompanyUserDTO createUserDto = sysUserFeign.queryByCompanyUserId(createUserId).getData();
            if (createUserDto != null) {
                //获取用户名
                docFileDto.setUserName(createUserDto.getUserName());
            }
            SysCompanyUserDTO companyUserDTO = sysUserFeign.queryByCompanyUserId(updateUserId).getData();
            if (companyUserDTO != null) {
                //获取最后更新用户名
                docFileDto.setUpdateUserName(companyUserDTO.getUserName());
            }
            return docFileDto;
        }).collect(Collectors.toList()); //遍历的数据 封装回List
        //返回数据
        return files;
    }

    /**
     * 获取指定目录下的文件夹
     *
     * @param parentFolderId
     * @param companyId
     * @return
     */
    private List<DocFolderDto> queryFolders(Long parentFolderId, Long companyId) {
        //组装查询条件
        LambdaQueryWrapper<DocFolder> folderWrapper = new LambdaQueryWrapper<>();
        folderWrapper.eq(DocFolder::getCompanyId, companyId);
        folderWrapper.eq(DocFolder::getParentId, parentFolderId);
        folderWrapper.eq(DocFolder::getStatus, (short) 1);

        List<DocFolder> folderList = folderMapper.selectList(folderWrapper);

        List<DocFolderDto> folders = BeanHelper.copyWithCollection(folderList, DocFolderDto.class);
        return folders;
    }

}